package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author llt
 * @since 2024-07-16
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final IInteractionReplyService replyService;

    private final UserClient userClient;

    private final SearchClient searchClient;

    private final CourseClient courseClient;

    private final CatalogueClient catalogueClient;

    private final CategoryCache categoryCache;


    @Override
    public void saveQuestion(QuestionFormDTO dto) {
        // 1. 获取当前登陆用户 id
        Long userId = UserContext.getUser();

        // 2. dto 转 po
        InteractionQuestion question = BeanUtils.copyBean(dto, InteractionQuestion.class);
        question.setUserId(userId);

        // 3. 保存
        this.save(question);
    }

    @Override
    public void updateQuestion(QuestionFormDTO dto, Long id) {
        // 1. 校验
        if (StringUtils.isBlank(dto.getTitle()) || StringUtils.isBlank(dto.getDescription()) || dto.getAnonymity() == null){
            throw new BadRequestException("非法参数");
        }
        InteractionQuestion question = this.getById(id);
        if (question == null) {
            throw new BadRequestException("非法参数: 不存在该id");
        }
        // 校验是否是正在修改自己的
        Long userId = UserContext.getUser();
        if (!userId.equals(question.getUserId())) {
            throw new BadRequestException("非法参数: 只能修改自己的 ");
        }

        // 2. dto 转 po
        question.setTitle(dto.getTitle());
        question.setDescription(dto.getDescription());
        question.setAnonymity(dto.getAnonymity());

        // 3. 修改
        this.updateById(question);
    }


    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery query) {
        // 1. 检验参数courseId
        if (query.getCourseId() == null) {
            throw new BadRequestException("课程 id 不能为空");
        }

        // 2. 获取用户id
        Long userId = UserContext.getUser();

        // 3. 分页查询互动问题
        Page<InteractionQuestion> page = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> !tableFieldInfo.getProperty().equals("description")) // 指定不查的字段
                .eq(InteractionQuestion::getCourseId, query.getCourseId())
                .eq(query.getOnlyMine(), InteractionQuestion::getUserId, userId)
                .eq(query.getSectionId() != null, InteractionQuestion::getSectionId, query.getSectionId())
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPage("create_time", false));

        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        // 4. 根据最新回答的id 批量查询回答信息
        Set<Long> latestAnswerIds = records.stream()
                .filter(c -> c.getLatestAnswerId() != null)
                .map(InteractionQuestion::getLatestAnswerId)
                .collect(Collectors.toSet());

        List<InteractionReply> replyList = new ArrayList<>();
        if (CollUtils.isNotEmpty(latestAnswerIds)) {
            replyList = replyService.lambdaQuery()
                    .in(InteractionReply::getId, latestAnswerIds)
                    .eq(InteractionReply::getHidden, false)
                    .list();
        }
        Map<Long, InteractionReply> replyMap = replyList.stream().collect(Collectors.toMap(InteractionReply::getId, c -> c));

        // 5. 远程调用 user 服务, 获取用户信息
        // 5.1 拿到用户id集合
        Set<Long> userIds = records.stream()
                .filter(c -> c.getAnonymity() != null)
                .map(InteractionQuestion::getUserId)
                .collect(Collectors.toSet());
        // 5.2 存入最新回答的用户id
        for (InteractionReply reply : replyList) {
            if (!reply.getAnonymity()) {
                userIds.add(reply.getUserId());
            }
        }
        // 5.3 远程调用
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        // 5.4 List 转 Map
        Map<Long, UserDTO> userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, c -> c));

        // 6. 封装 vo 返回
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionVO vo = new QuestionVO();

            BeanUtils.copyBean(record, QuestionVO.class);

            if (!record.getAnonymity()) {
                UserDTO userDTO = userDTOMap.get(record.getUserId());
                if (userDTO != null) {
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                }
            }

            InteractionReply reply = replyMap.get(record.getLatestAnswerId());
            if (reply != null) {
                if (!reply.getAnonymity()) {
                    UserDTO userDTO = userDTOMap.get(reply.getUserId());
                    if (userDTO != null) {
                        vo.setLatestReplyUser(userDTO.getName());// 最新回答者的昵称--非匿名才设置
                    }
                }
                vo.setLatestReplyContent(reply.getContent());// 最新回答者的信息
            }


            voList.add(vo);
        }

        return PageDTO.of(page, voList);
    }


    @Override
    public QuestionVO queryQuestionById(Long id) {
        // 1. 校验
        if (id == null) {
            throw new BadRequestException("非法参数");
        }

        // 2. 查询互动问题表-主键
        InteractionQuestion question = this.getById(id);
        if (question == null) {
            throw new BadRequestException("问题不存在");
        }

        // 3. 如果问题为隐藏, 返回null
        if (question.getHidden()) {
            return null;
        }

        // 4. 封装 vo 返回
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);

        // 5. 如果用户匿名提问, 不用查询昵称和头像
        if (!question.getAnonymity()) {
            // 5.1 远程调用用户服务
            UserDTO userDTO = userClient.queryUserById(id);
            if (userDTO != null) {
                // 给 vo 填值
                vo.setUserName(userDTO.getName());
                vo.setUserIcon(userDTO.getIcon());
            }
        }

        return vo;
    }

    @Override
    public PageDTO<QuestionAdminVO> queryQuestionAdminVOPage(QuestionAdminPageQuery query) {
        // 0. 如果用户传了课程的名称, 从 es 中获取该课程名称对应的课程id
        String courseName = query.getCourseName();
        List<Long> cids = null;
        if (StringUtils.isNotBlank(courseName)) {
            // 0.1 通过 feign 调用搜索服务, 获取到课程id
            cids = searchClient.queryCoursesIdByName(courseName);

            if (CollUtils.isEmpty(cids)) {
                return PageDTO.empty(0L, 0L);
            }
        }

        // 1. 查询互动问题表(根据前端传的参数查, 分页, 按照提问时间倒序)
        Page<InteractionQuestion> page = this.lambdaQuery()
                .in(CollUtils.isNotEmpty(cids), InteractionQuestion::getCourseId, cids)
                .eq(query.getStatus() != null, InteractionQuestion::getStatus, query.getStatus())
                .between(query.getBeginTime() != null && query.getEndTime() != null,
                        InteractionQuestion::getCreateTime, query.getBeginTime(), query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());

        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        Set<Long> uids = new HashSet<>(); // userId集合
        Set<Long> courseIds = new HashSet<>(); // 课程id集合
        Set<Long> csids = new HashSet<>();// 章和节id集合
        for (InteractionQuestion record : records) {
            uids.add(record.getUserId());

            courseIds.add(record.getCourseId());

            csids.add(record.getChapterId());
            csids.add(record.getSectionId());
        }

        // 2. 远程调用用户服务 获取用户信息
        List<UserDTO> uinfos = userClient.queryUserByIds(uids);
        if (CollUtils.isEmpty(uinfos)) {
            throw new BadRequestException("用户不存在");
        }
        Map<Long, UserDTO> uinfoMap = uinfos.stream().collect(Collectors.toMap(UserDTO::getId, c -> c));

        // 3. 远程掉用课程服务 获取课程信息
        List<CourseSimpleInfoDTO> cinfos = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(cinfos)) {
            throw new BadRequestException("课程不存在");
        }
        Map<Long, CourseSimpleInfoDTO> cinfoMap = cinfos.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        // 4. 远程调用课程服务 获取章节信息
        List<CataSimpleInfoDTO> csinfos = catalogueClient.batchQueryCatalogue(csids);
        if (CollUtils.isEmpty(csinfos)) {
            throw new BadRequestException("章节不存在");
        }
        Map<Long, String> csinfoMap = csinfos.stream()
                .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));

        // 6. po 转 vo 返回
        List<QuestionAdminVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionAdminVO vo = BeanUtils.copyBean(record, QuestionAdminVO.class);

            UserDTO userInfoDTO = uinfoMap.get(record.getUserId());
            if (userInfoDTO != null) {
                vo.setUserName(userInfoDTO.getName());
            }

            CourseSimpleInfoDTO cinfoDTO = cinfoMap.get(record.getCourseId());
            if (cinfoDTO != null) {
                vo.setCourseName(cinfoDTO.getName());

                // 5. 获取课程一二三级分类id
                List<Long> categoryIds = cinfoDTO.getCategoryIds();
                // 5.2 获取分类名字
                String categoryNames = categoryCache.getCategoryNames(categoryIds);

                vo.setCategoryName(categoryNames); //三级分类名称, 拼接字段
            }

            vo.setChapterName(csinfoMap.get(record.getChapterId())); // 章名称
            vo.setSectionName(csinfoMap.get(record.getSectionId())); // 节名称
        }

        return PageDTO.of(page, voList);
    }
}
